#pragma once

#include "hdmap/HDMapExports.hpp"
#include "hdmap/HDMapCommon.hpp"

namespace Navinfo
{
	namespace Engine
	{
		/**
		 *  @brief Location object infomation
		 */
		class HDMAP_API_PUBLIC HDMapObjectInfo
		{
		public:
			friend class HDMapImpl;

			HDMapObjectInfo(){}
			virtual ~HDMapObjectInfo(){}
			/**
			 *  @brief get type for object
			 *  @note all objects have this property
			 */
			virtual HDMapObjectType GetObjectType() const { return mObjectType; }
			/**
			 *  @brief get id for object
			 *  @note all objects have this property
			 */
			virtual uint64_t GetObjectID() const { return mObjectID; }
			/**
			 *  @brief get height for pole or obstacle
			 *  @note only pole object and obstacle object have this property
			 */
			virtual ObjectHeight GetHeight() const { return val_Height; }
			/**
			 *  @brief get shape for trafic sign
			 *  @note only sign object have this property
			 */
			virtual TraficSignShape GetSignShp() const { return val_TrSignShp; }
			/**
			 *  @brief get type for trafic sign
			 *  @note only sign objec have this property
			 */
			virtual TraficSignType GetSignType() const { return val_TrSignType; }
			/**
			 *  @brief get heading value for traffic sign.
			 *  The value is degree angle from true north turn to the orientation of this signage facing which in a clockwise direction.
			 *  Unit: 0.0001 degree
			 *  @note only sign object have this property
			 */
			virtual uint32_t GetSignHeading() const { return val_TrSignHeading; }
			/**
			 *  @brief get color of the traffic sign
			 *  @note only sign object have this property
			 */
			virtual SignColor GetSignColor() const { return val_Color; }
			/**
			 *  @brief get upper diameter for pole
			 *  @note only pole object have this property
			 */
			virtual UpperDiameter GetPoleUpperDM() const { return val_UpperDM; }
			/**
			 *  @brief get lower diameter for pole
			 *  @note only pole object have this property
			 */
			virtual LowerDiameter GetPoleLowerDM() const { return val_LowerDM; }
			/**
			 *  @brief get color for marking
			 *  @note only pole object have this property
			 */
			virtual MarkingColor GetMarkingColor() const { return val_Color; }
			/**
			 *  @brief get type for marking
			 *  @note only marking object have this property
			 */
			virtual MarkingType GetMarkingType() const { return val_MarkingType; }
			/**
			 *  @brief get geometry type for marking
			 *  @note only marking object have this property
			 */
			virtual MarkingGeometryType GetMarkingGeometryType() const { return val_GeometryType; }
			/**
			 *  @brief get type for pole
			 *  @note only pole object have this property
			 */
			virtual PoleObjectType GetPoleType() const { return val_PoleType; }
			
			/**
			 *  @brief get geometry for object.
			 *  @note each type of object have difference geometry shape
			 *  <br/>
			 *  <ul>
			 *  <li>1.for sign object: round shape store vertex of inscribed triangle for the traffic sign, other shape store bounding box around the traffic sign which in a clockwise direction.
			 *  <li>2.for pole object: geometry contain one or two coordnate.
			 *      <br/>first point store the point where the pole intersects with the ground it is standing upon.
			 *      <br/>second point store top of the pole if it exists.
			 *  <li>3.for marking object:
			 *      <br/>geometry approximated centerline of the marking when the Landmark geometry type is GEOMETRY_CENTER_LINE.
			 *      <br/>geometry store a bounding box around the marking when geometry type is GEOMETRY_BOUNDARY_BOX
			 *  <li>4.for traffic light object: geometry stored the bounding box is defined in the 3d space
			 *  <li>5.for wall object: the outline is defined by 3 or more points 
			 *  <li>6.for over head struct object: the outline is defined by 3 or more points 
			 *  <li>7.for barrier object: geometry store shape of the barrier stored as multiple polylines.
			 *  <li>8.for obstacle object: geometry store a multiple polylines
			 *  </ul>
			 */
			virtual const std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> &GetGeometryPoints() const { return mMultiObjectVertex; }
		protected:/**@privatesection*/
			/**
			 *  @brief set height of location object
			 */
			virtual void SetHeight(const ObjectHeight& val) { val_Height = val; }
			/**
			 *  @brief set shape if trafic sign
			 */
			virtual void SetSignShp(const TraficSignShape& val) { val_TrSignShp = val; }
			/**
			 *  @brief set type if trafic sign
			 */
			virtual void SetSignType(const TraficSignType& val) { val_TrSignType = val; }
			/**
			 *  @brief set sign content value e.g speedlimit value
			 */
			virtual void SetSignContent(const TrafficSignContent &val) { val_TrSignContent = val; }
			/**
			 *  @brief set sign heading value
			 */
			virtual void SetSignHeading(const uint32_t &val){ val_TrSignHeading = val; }
			/**
			 *  @brief set sign color value
			 */
			virtual void SetSignColor(const SignColor& val) { val_Color = val; }
			/**
			 *  @brief set Upper Diameter
			 */
			virtual void SetPoleUpperDM(const UpperDiameter& val) { val_UpperDM = val; }
			/**
			 *  @brief set Lower Diameter
			 */
			virtual void SetPoleLowerDM(const LowerDiameter& val) { val_LowerDM = val; }
			/**
			 *  @brief set color of location object
			 */
			virtual void SetMarkingColor(const MarkingColor& val) { val_Color = val; }
			/**
			 *  @brief set marking type for land marking
			 */
			virtual void SetMarkingType(const MarkingType& val) { val_MarkingType = val; }
			/**
			 *  @brief set geometry indicater for lane marking geometry
			 */
			virtual void SetMarkingGeometryType(const MarkingGeometryType& val) { val_GeometryType = val; }
			/**
			 *  @brief set pole type for pole like object
			 */
			virtual void SetPoleType(const PoleObjectType& val) { val_PoleType = val; }

			/**
			 *  @brief add a list of coord
			 */
			virtual void AddVertexList(const std::vector<Navinfo::Engine::Math::Vec3d> &vertexList) final
			{
				mMultiObjectVertex.push_back(vertexList);
			}
			/**
			 *  @brief add a coord on first list of coord container
			 */
			virtual void AddVertex(const Navinfo::Engine::Math::Vec3d &coord) final
			{
				mMultiObjectVertex[0].push_back(coord);
			}
		protected:/**@privatesection*/
			uint64_t				mObjectID;				///< object id
			HDMapObjectType         mObjectType;			///< location object type
			
			TraficSignShape			val_TrSignShp;			///< shape of traffic sign
			TraficSignType			val_TrSignType;			///< type of traffic sign
			TrafficSignContent		val_TrSignContent;		///< content value of traffic sign e.g speed limit value on sign
			uint32_t				val_TrSignHeading;		///< 0,3600000; Unit - 0.0001 degree;

			ObjectHeight			val_Height;				///< Object height pole or barriers	
			UpperDiameter			val_UpperDM;			///< Diameter of the pole on top
			LowerDiameter			val_LowerDM;			///< Diameter of the pole
			PoleObjectType			val_PoleType;			///< Type of pole

			TrafficLightType 		mTraffictType;			///< Type of trafficlight
			TrafficLightOrientation mOrientation;			///< Orientation of traffic light configurati 
			int8_t 					mTierNum;				///< Number of tiers: columns of lights in a vertical signal, rows in a orizontal signal
			int8_t 					mLightNum;				///< Number of lights in each tier

			MarkingColor 			val_Color;				///< color of marking
			MarkingType 			val_MarkingType;		///< type of marking
			MarkingGeometryType 	val_GeometryType;		///< geometry of marking

			std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> 	mMultiObjectVertex; ///< shape point coordinates
			std::vector<Navinfo::Engine::Math::LineSegment2d>		m_vtSegments;		///< shep segment of object
		};

		/**
		 *  @brief object of traffic sign
		 */
		class HDMAP_API_PUBLIC HDMapObjectSign : public HDMapObjectInfo
		{
		public:
			HDMapObjectSign(){ mObjectType = OBJECT_TYPE_SIGN; }
			virtual HDMapObjectType GetObjectType() const { return mObjectType; }
			virtual uint64_t GetObjectID() const { return mObjectID; }
			virtual TraficSignShape GetSignShp() const { return val_TrSignShp; }
			virtual TraficSignType GetSignType() const { return val_TrSignType; }
			virtual uint32_t GetSignHeading()const { return val_TrSignHeading; }
			virtual SignColor GetSignColor() const { return val_Color; }
			virtual const std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> &GetGeometryPoints() const { return mMultiObjectVertex; }
		};
		/**
		 *  @brief pole like object
		 */
		class HDMAP_API_PUBLIC HDMapObjectPole : public HDMapObjectInfo
		{
		public:
			HDMapObjectPole(){ mObjectType = OBJECT_TYPE_POLE; }
			virtual HDMapObjectType GetObjectType() const { return mObjectType; }
			virtual uint64_t GetObjectID() const { return mObjectID; }
			virtual ObjectHeight GetHeight() const { return val_Height; }
			virtual UpperDiameter GetPoleUpperDM() const { return val_UpperDM; }
			virtual LowerDiameter GetPoleLowerDM() const { return val_LowerDM; }
			virtual const std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> &GetGeometryPoints() const { return mMultiObjectVertex; }
		};

		/**
		 *  @brief traffic light object
		 */
		class HDMAP_API_PUBLIC HDMapObjectTrafficLight : public HDMapObjectInfo
		{
		public:
			HDMapObjectTrafficLight(){ mObjectType = OBJECT_TYPE_TRAFICLIGHT; }
			virtual HDMapObjectType GetObjectType() const { return mObjectType; }
			virtual uint64_t GetObjectID() const { return mObjectID; }
			virtual TraficSignShape GetSignShp() const { return val_TrSignShp; }
			virtual TraficSignType GetSignType() const { return val_TrSignType; }
			virtual const std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> &GetGeometryPoints() const { return mMultiObjectVertex; }
		};

		/**
		 *  @brief marking object on road
		 */
		class HDMAP_API_PUBLIC HDMapObjectMarking : public HDMapObjectInfo
		{
		public:
			HDMapObjectMarking(){ mObjectType = OBJECT_TYPE_MARKING; }
			virtual HDMapObjectType GetObjectType() const { return mObjectType; }
			virtual uint64_t GetObjectID() const { return mObjectID; }
			virtual MarkingColor GetMarkingColor() const { return val_Color; }
			virtual MarkingType GetMarkingType() const { return val_MarkingType; }
			virtual MarkingGeometryType GetMarkingGeometryType() const { return val_GeometryType; }
			virtual const std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> &GetGeometryPoints() const { return mMultiObjectVertex; }
		};

		/**
		 *  @brief perpendicular wall on road, like wall on enterance of tunnel
		 */
		class HDMAP_API_PUBLIC HDMapObjectWall : public HDMapObjectInfo
		{
		public:
			HDMapObjectWall(){ mObjectType = OBJECT_TYPE_WALL; }
			virtual HDMapObjectType GetObjectType() const { return mObjectType; }
			virtual uint64_t GetObjectID() const { return mObjectID; }
			virtual const std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> &GetGeometryPoints() const { return mMultiObjectVertex; }
		};

		/**
		 *  @brief obstacle object on road
		 */
		class HDMAP_API_PUBLIC HDMapObjectObstacle : public HDMapObjectInfo
		{
		public:
			HDMapObjectObstacle(){ mObjectType = OBJECT_TYPE_OBSTACLE; }
			virtual HDMapObjectType GetObjectType() const { return mObjectType; }
			virtual uint64_t GetObjectID() const { return mObjectID; }
			virtual ObjectHeight GetHeight() const { return val_Height; }
			virtual const std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> &GetGeometryPoints() const { return mMultiObjectVertex; }
		};

		/**
		 *  @brief traffic barrier object
		 */
		class HDMAP_API_PUBLIC HDMapObjectBarrier : public HDMapObjectInfo
		{
		public:
			HDMapObjectBarrier(){ mObjectType = OBJECT_TYPE_BARRIER; }
			virtual HDMapObjectType GetObjectType() const { return mObjectType; }
			virtual uint64_t GetObjectID() const { return mObjectID; }
			virtual const std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> &GetGeometryPoints() const { return mMultiObjectVertex; }
		};

		/**
		 *  @brief  Overhead Structure Face object
		 */
		class HDMAP_API_PUBLIC HDMapObjectOSF : public HDMapObjectInfo
		{
		public:
			HDMapObjectOSF(){ mObjectType = OBJECT_TYPE_OSF; }
			virtual HDMapObjectType GetObjectType() const { return mObjectType; }
			virtual uint64_t GetObjectID() const { return mObjectID; }
			virtual const std::vector<std::vector<Navinfo::Engine::Math::Vec3d>> &GetGeometryPoints() const { return mMultiObjectVertex; }
		};
	} 
}
namespace Navinfo{
	namespace HDMap{
		typedef Navinfo::Engine::HDMapObjectInfo Object;
	}
}